/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2007，所有权利保留。
 * 
 * 项目名：	rumba
 * 文件名：	HTable.java
 * 模块说明：	
 * 修改历史：
 * Aug 24, 2007 - lxm - 创建。
 */
package com.hd123.rumba.jsp.table;

import java.util.ArrayList;
import java.util.List;

import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.request.Dictionary;
import com.hd123.rumba.request.JspLib;
import com.hd123.rumba.util.AccessMode;

/**
 * 可编辑表格控件。<br>
 * 
 * <br>
 * 需要的js文件：
 * <dl>
 * <dd>rumba/script/field/RField.js
 * <dd>rumba/script/table/RTable.js
 * </dl>
 * 
 * @author lxm
 * 
 */
public class HTable {

  public HTable(Dictionary dd, String name, HDataset dataset) {
    super();
    this.dd = dd;
    this.name = name;
    this.dataset = dataset;
  }

  private String name;
  private HDataset dataset;
  private Dictionary dd;
  private Integer height;
  private Boolean readonly;
  private List<HColumnDef> columnDefs = new ArrayList<HColumnDef>();

  /** 属性：数据集。 */
  public HDataset getDataset() {
    return dataset;
  }

  public void setDataset(HDataset dataset) {
    this.dataset = dataset;
  }

  /** 属性：控件高度。允许null，表示不指定控件的高度。默认为null。 */
  public Integer getHeight() {
    return height;
  }

  public void setHeight(Integer height) {
    this.height = height;
  }

  /** 属性：对象标识。 */
  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  /** 属性：表示控件是否出于只读状态。默认为false。 */
  public Boolean getReadonly() {
    return readonly;
  }

  public void setReadonly(Boolean readonly) {
    this.readonly = readonly;
  }

  /** 属性：数据字典。 */
  public Dictionary getDd() {
    return dd;
  }

  public void setDd(Dictionary dd) {
    this.dd = dd;
  }

  /** 属性：列定义列表 */
  public List<HColumnDef> getColumnDefs() {
    return columnDefs;
  }

  public void setColumnDefs(List<HColumnDef> columnDefs) {
    this.columnDefs = columnDefs;
  }

  /**
   * 输出HTML字符串。
   * 
   * @return 返回符合HTML语法的字符串，可以将其直接嵌入页面使用。
   */
  public String toHTML() throws BusinessException {
    if (this.dataset == null) 
      throw new BusinessException("属性dataset不可为空。");
    
    StringBuffer sb = new StringBuffer();
    sb.append("<span id='");
    sb.append(this.name);
    sb.append("'></span>");
    sb.append("<script language='javascript'>");
    String formState = (String) dd.getFormValue(JspLib.ID_FORMSTATE);
    sb.append(this.toJS(formState));
    sb.append("</script>");
    return sb.toString();
  }

  /**
   * 清除所有列定义。
   * 
   */
  public void clearColumnDefs() {
    if (this.columnDefs == null)
      this.columnDefs = new ArrayList<HColumnDef>();
    else
      this.columnDefs.clear();
  }

  /**
   * 添加一个列定义。
   * 
   * @param fieldName
   *          指定字段名。
   * @param caption
   *          指定列标题。
   * @param params
   *          其它参数数组。可用的参数说明参见{@link HColumnDef}相应的属性说明。
   * @return 返回创建的列定义对象。
   * @throws BusinessException
   */
  public HColumnDef appendColumnDef(String fieldName, String caption, Object[] params)
      throws BusinessException {
    if (fieldName == null)
      throw new BusinessException("必须的参数fieldName不可为null。");
    if (caption == null)
      throw new BusinessException("必须的参数caption不可为null。");
    HColumnDef colDef = this.getColumnDefByFieldName(fieldName);
    if (colDef != null)
      throw new BusinessException("已经存在相同字段名的列定义。");
    colDef = new HColumnDef(fieldName, caption, params);
    colDef.setTable(this);
    this.columnDefs.add(colDef);
    return colDef;
  }

  /**
   * 根据字段名取得列定义
   * 
   * @param fieldName
   *          指定字段名。
   * @return 返回符合条件的列定义对象，若找不到则返回null。
   */
  public HColumnDef getColumnDefByFieldName(String fieldName) {
    HColumnDef columnDef = null;
    for (HColumnDef colDef : this.columnDefs)
      if (colDef.getFieldName().equals(fieldName)) {
        columnDef = colDef;
        break;
      }
    return columnDef;
  }
  
  String getTable_VarJS() {
    return "tbl" + this.name;
  }
  
  String getDataset_VarJS() {
    return "ds" + this.name;
  }
  
  private String toJS(String formState) throws BusinessException {
    StringBuffer sb = new StringBuffer();
    String tbl = this.getTable_VarJS();
    sb.append("var " + tbl + " = null;\n");
    sb.append("function loadPage_" + tbl + "() {\n");
    sb.append(tbl + " = new RTable();\n");
    if (this.height != null)
      sb.append(tbl + ".height = '" + this.height + "';\n");
    sb.append(this.toJS_columnDefs(tbl, formState));
    sb.append(this.toJS_dataset(tbl));
    if (JspLib.VALUE_FORMSTATE_VIEW.equals(formState))
      sb.append(tbl + ".setReadonly(true);\n");
    sb.append(tbl + ".showIn($('" + this.name + "'));\n");
    sb.append("}\n");
    sb.append("registerLoadPage('loadPage_" + tbl + "()');\n");
    return sb.toString();
  }
  
  private String toJS_columnDefs(String tbl, String formState) {
    StringBuffer sb = new StringBuffer();
    sb.append(tbl + ".clearColumnDefs();\n");
    for (HColumnDef columnDef : this.columnDefs)
      sb.append(columnDef.toJS(formState));
    return sb.toString();
  }
  
  private String toJS_dataset(String tbl) throws BusinessException {
    StringBuffer sb = new StringBuffer();
    String ds = this.getDataset_VarJS();
    sb.append("var " + ds + " = new RDataset();\n");
    AccessMode am = (AccessMode) dd.get("am");
    sb.append(ds + ".deserialize('" + this.dataset.serialize(am) + "');\n");
    sb.append(tbl + ".setDataset(" + ds + ");\n");
    return sb.toString();
  }
}
